use std::num::NonZeroUsize;

use crate::cpl::CslStringList;
use crate::errors;
use crate::raster::processing::dem::options::common_dem_options;

use super::options::CommonOptions;

/// Configuration options for [`topographic_position_index()`][super::topographic_position_index()].
#[derive(Debug, Clone, Default)]
pub struct TpiOptions {
    common_options: CommonOptions,
}

impl TpiOptions {
    /// Create a DEM-topographic-position-index options set.
    pub fn new() -> Self {
        Default::default()
    }

    common_dem_options!();

    /// Render options into [`CslStringList`] values, as compatible with
    /// [`gdal_sys::GDALDEMProcessing`].
    pub fn to_options_list(&self) -> errors::Result<CslStringList> {
        let mut opts = CslStringList::new();
        self.store_common_options_to(&mut opts)?;
        Ok(opts)
    }
}

#[cfg(test)]
mod tests {
    use crate::assert_near;
    use crate::cpl::CslStringList;
    use crate::errors::Result;
    use crate::raster::processing::dem::topographic_position_index;
    use crate::raster::processing::dem::tpi::TpiOptions;
    use crate::raster::StatisticsAll;
    use crate::test_utils::{fixture, InMemoryFixture};
    use crate::Dataset;

    #[test]
    fn test_options() -> Result<()> {
        let mut proc = TpiOptions::new();
        proc.with_input_band(2.try_into().unwrap())
            .with_compute_edges(true)
            .with_output_format("GTiff")
            .with_additional_options("CPL_DEBUG=ON".parse()?);

        let expected: CslStringList = "-compute_edges -b 2 -of GTiff CPL_DEBUG=ON".parse()?;
        assert_eq!(expected.to_string(), proc.to_options_list()?.to_string());

        Ok(())
    }
    #[test]
    fn test_tpi() -> Result<()> {
        let opts = TpiOptions::new();

        let ds = Dataset::open(fixture("dem-hills.tiff"))?;

        let output = InMemoryFixture::new("dem-hills-tpi.tiff");
        let slope = topographic_position_index(&ds, output.path(), &opts)?;

        let stats = slope.rasterband(1)?.get_statistics(true, false)?.unwrap();

        // These numbers were generated by extracting the output from:
        //    gdaldem tpi fixtures/dem-hills.tiff target/dest.tiff
        //    gdalinfo -stats target/dest.tiff
        let expected = StatisticsAll {
            min: -4.7376708984375,
            max: 4.7724151611328,
            mean: 0.00012131847966826,
            std_dev: 0.48943078832474,
        };

        assert_near!(StatisticsAll, stats, expected, epsilon = 1e-10);
        Ok(())
    }
}
